/** 
Copyright (c) 2010, Sheikh Abdul Wahid Ahmed
Details @ http://extremecodeworld.codeplex.com/license
**/

using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using EXtremecode.Common.UI;
using System.Collections;

namespace EXtremecode.PresentationLayer
{
    /// <summary>
    /// Summary description for Decorator
    /// </summary>
    #region Factories
    
    public class RSPDecorator : IDecorator
    {
        
        private static IFrameSubDecorator frameSubDecorator = new RSPFrameSubDecorator();
        private static IFrameWindowSubDecorator frameWindowSubDecorator = new RSPFrameWindowSubDecorator();
        private static IButtonSubDecorator buttonSubDecorator = new RSPButtonSubDecorator();

        public void DecorateFrame(object tbl, string title,string imageURL)
        {
            frameSubDecorator.Decorate(tbl, title,imageURL);
        }

        public void DecorateFrameWindow(object obj, string title,string imageURL)
        {
            frameWindowSubDecorator.Decorate(obj, title,imageURL);
        }
           
        public void DecorateButton(object obj, string caption,string imageURL)
        {
            buttonSubDecorator.Decorate(obj, caption,imageURL);
        }

       
    }
    #endregion

    #region Factories sub parts

    
    public class RSPFrameSubDecorator : IFrameSubDecorator
    {
        public void Decorate(object obj, string title,string imageURL)
        {
            Table tbl = obj as Table;
            if (tbl == null)
            {
                throw new Exception("Decorated object should be a Table control");
            }
            tbl.CssClass = "rspFrameTable";
            tbl.CellPadding = tbl.CellSpacing = 0;
            tbl.BorderWidth = Unit.Pixel(0);

            //GetFirstRow if its type is FrameHeader then remove it.
            //And create new table, insert this row into it 
            //and insert this table into the middle cell of top row
            TableCell barInternalTableContainer = null;
            if (tbl.Rows.Count > 0 && tbl.Rows[0] is FrameHeader)
            {
                //create new table
                Table barTable = new Table();
                barTable.SkinID = "RSPBarInternalTable";

                //remove first row.
                TableRow tr = tbl.Rows[0];
                tbl.Rows.Remove(tr);

                //add delted row to barTable
                barTable.Rows.Add(tr);

                //add bar table to middle cell.
                barInternalTableContainer = new TableCell();
                barInternalTableContainer.Controls.Add(barTable);
                barInternalTableContainer.SkinID = "RSPBarInternalTableContainerCell";

            }

            //bar it self a table which contains single row and this row contains
            //four cells. and these cells for
            //LEFT CURVE,TITLE,INTERNAL TABLE and RIGHT CURVE respectively. 

            //create barTable
            Table tblBar = new Table();
            tblBar.SkinID = "RSPBarTable";
            TableRow rowBar = new TableRow();
            tblBar.Rows.Add(rowBar);

            //create four cell
            TableCell cellLeftCurve = new TableCell();
            TableCell cellTitle = new TableCell();
            TableCell cellInternalTable = (barInternalTableContainer != null) ?
                barInternalTableContainer : new TableCell();
            TableCell cellRightCurve = new TableCell();

            //left curve
            cellLeftCurve.SkinID = "RSPBarLeftCurve";
            Image imgLeftCurve = new Image();
            imgLeftCurve.SkinID = "RSPLeftImage";
            cellLeftCurve.Controls.Add(imgLeftCurve);
            rowBar.Cells.Add(cellLeftCurve);

            //title
            cellTitle.SkinID = "RSPBarTitleCell";
            Label lblTitle = new Label();
            lblTitle.Text = title;
            lblTitle.SkinID = "RSPTitle";
            cellTitle.Controls.Add(lblTitle);
            rowBar.Cells.Add(cellTitle);


            //internal table
            rowBar.Cells.Add(cellInternalTable);


            //Right curve
            cellRightCurve.SkinID = "RSPBarRightCurve";
            Image imgRightCurve = new Image();
            imgRightCurve.SkinID = "RSPRightImage";
            cellRightCurve.Controls.Add(imgRightCurve);
            rowBar.Cells.Add(cellRightCurve);

            //now insert new row and add this bar table into it. we need colspan for this row so first calcuate it.

            //Get sum of colspan
            int colspan = 0;
            if (tbl.Rows.Count > 0)
            {
                foreach (TableCell tc in tbl.Rows[0].Cells)
                {
                    colspan += (tc.ColumnSpan == 0) ? 1 : tc.ColumnSpan;
                }
            }

            //create first row [bar table container]
            TableRow firstRow = new TableRow();
            firstRow.Cells.Add(new TableCell());
            firstRow.Cells[0].ColumnSpan = colspan;
            firstRow.Cells[0].Controls.Add(tblBar);
            tbl.Rows.AddAt(0, firstRow);
        }
    }

    public class RSPFrameWindowSubDecorator : IFrameWindowSubDecorator
    {
        public void Decorate(object obj, string title,string imageURL)
        {
            Table tbl = obj as Table;
            if (tbl == null)
            {
                throw new Exception("Decorated object should be a Table control");
            }
            tbl.CssClass = "rspFrameWindowTable";
            tbl.CellPadding = tbl.CellSpacing = 0;
            tbl.BorderWidth = Unit.Pixel(0);

            AddSplitters(tbl);
            SurroundWithBorder(tbl,title,imageURL);

            
            


        }
        private void SurroundWithBorder(Table tbl,string title,string imageURL)
        {
            //First we create new table and move all rows from tbl to this new table.
            //then add this new table into another newTable and create a new row into second new table for
            //displaying title.

            Table newTable = new Table();
            newTable.SkinID = "RSPWindowContentTable";
            TableRow[] tblRows =new TableRow[tbl.Rows.Count];
            tbl.Rows.CopyTo(tblRows, 0);
            tbl.Rows.Clear();
            newTable.Rows.AddRange(tblRows);
            
            Table secondNewTable = new Table();
            secondNewTable.CellPadding = secondNewTable.CellSpacing = 0;
            secondNewTable.BorderWidth = Unit.Pixel(0);
            int contentCell_ColSpan = 1;

            //add title
            if (!string.IsNullOrEmpty(title))
            {
                TableRow titleRow = new TableRow();
                titleRow.SkinID = "RSPFrameWindowTitleRow";
                secondNewTable.Rows.Add(titleRow);


                if (!string.IsNullOrEmpty(imageURL))
                {
                    Image headerImage = new Image();
                    headerImage.ImageUrl = imageURL;
                    TableCell imageCell = new TableCell();
                    imageCell.Controls.Add(headerImage);
                    titleRow.Cells.Add(imageCell);
                    imageCell.SkinID = "RSPFrameWindowTitleImageCell";
                    contentCell_ColSpan++;
                }
                Label lblTitle = new Label();
                lblTitle.SkinID = "RSPFrameWindowTitle";
                lblTitle.Text = title;
                TableCell titleCell = new TableCell();



                titleCell.SkinID = "RSPFrameWindowTitleCell";
                titleCell.Controls.Add(lblTitle);
                titleRow.Cells.Add(titleCell);

                // for keeping gaps
                TableRow gapRow = new TableRow();
                gapRow.SkinID = "RSPFrameWindowContentGapRow";
                secondNewTable.Rows.Add(gapRow);
            }
            
            //add first new table
            TableCell contentCell = new TableCell(); //containing first new table.
            TableRow contentRow = new TableRow();
            contentCell.ColumnSpan = contentCell_ColSpan;

            secondNewTable.Rows.Add(contentRow);
            contentRow.Cells.Add(contentCell);
            contentCell.Controls.Add(newTable);
           

            //add three rows in tbl.
            TableRow firstRow = new TableRow(); tbl.Rows.Add(firstRow);
            TableRow secondRow = new TableRow(); tbl.Rows.Add(secondRow);
            TableRow thirdRow = new TableRow(); tbl.Rows.Add(thirdRow);



            //**First Row
            //contains three cell 
            //UpperLeftCurve,TopCenterLine and UpperRightCurve
            TableCell cellUpperLeftCurve = new TableCell();
            TableCell cellTopCenterLine = new TableCell();
            TableCell cellUpperRightCurve = new TableCell();

            //UpperLeftCurve
            cellUpperLeftCurve.SkinID = "RSPWindowUpperLeftCurveCell";
            Image imgUpperLeftCurve = new Image();
            imgUpperLeftCurve.SkinID = "RSPWindowUpperLeftCurveImage";
            cellUpperLeftCurve.Controls.Add(imgUpperLeftCurve);
            firstRow.Cells.Add(cellUpperLeftCurve);

            //TopCenterLine
            cellTopCenterLine.SkinID = "RSPWindowTopCenterLineCell";
            Image imgTopCenterLine = new Image();
            imgTopCenterLine.SkinID = "RSPWindowTopCenterLineImage";
            cellTopCenterLine.Controls.Add(imgTopCenterLine);
            firstRow.Cells.Add(cellTopCenterLine);


            //UpperRightCurve
            cellUpperRightCurve.SkinID = "RSPWindowUpperRightCurveCell";
            Image imgUpperRightCurve = new Image();
            imgUpperRightCurve.SkinID = "RSPWindowUpperRightCurveImage";
            cellUpperRightCurve.Controls.Add(imgUpperRightCurve);
            firstRow.Cells.Add(cellUpperRightCurve);



            //**Second Row
            //contains three cell 
            //MiddleLeftLine, cell for secondNewTable and MiddleRightLine
            TableCell cellMiddleLeftLine = new TableCell();
            TableCell cellNewTable = new TableCell();
            TableCell cellMiddleRightLine = new TableCell();

            //MiddleLeftLine
            cellMiddleLeftLine.SkinID = "RSPWindowMiddleLeftLineCell";
            secondRow.Cells.Add(cellMiddleLeftLine);

            //NewTable 
            cellNewTable.SkinID = "RSPWindowContentCell";
            cellNewTable.Controls.Add(secondNewTable);
            secondRow.Cells.Add(cellNewTable);


            //MiddleRightLine
            cellMiddleRightLine.SkinID = "RSPWindowMiddleRightLineCell";
            secondRow.Cells.Add(cellMiddleRightLine);


            //**Third Row
            //contains three cell 
            //LowerLeftCurve,BottomCenterLine and LowerRightCurve
            TableCell cellLowerLeftCurve = new TableCell();
            TableCell cellBottomCenterLine = new TableCell();
            TableCell cellLowerRightCurve = new TableCell();

            //LowerLeftCurve
            cellLowerLeftCurve.SkinID = "RSPWindowLowerLeftCurveCell";
            Image imgLowerLeftCurve = new Image();
            imgLowerLeftCurve.SkinID = "RSPWindowLowerLeftCurveImage";
            cellLowerLeftCurve.Controls.Add(imgLowerLeftCurve);
            thirdRow.Cells.Add(cellLowerLeftCurve);

            //BottomCenterLine
            cellBottomCenterLine.SkinID = "RSPWindowBottomCenterLineCell";
            Image imgBottomCenterLine = new Image();
            imgBottomCenterLine.SkinID = "RSPWindowBottomCenterLineImage";
            cellBottomCenterLine.Controls.Add(imgBottomCenterLine);
            thirdRow.Cells.Add(cellBottomCenterLine);


            //LowerRightCurve
            cellLowerRightCurve.SkinID = "RSPWindowLowerRightCurveCell";
            Image imgLowerRightCurve = new Image();
            imgLowerRightCurve.SkinID = "RSPWindowLowerRightCurveImage";
            cellLowerRightCurve.Controls.Add(imgLowerRightCurve);
            thirdRow.Cells.Add(cellLowerRightCurve);



        }

        private void AddSplitters(Table tbl)
        {
            //Make array of rows of current table
            ArrayList rows = new ArrayList(); //for visible rows
            ArrayList invisibleRows = new ArrayList(); //for invisible rows
            foreach (TableRow tr in tbl.Rows)
            {
                if (tr.Visible)
                {
                    rows.Add(tr);
                }
                else
                {
                    invisibleRows.Add(tr);
                }
            }

            //Remove invisible rows.
            foreach (TableRow tr in invisibleRows)
            {
                tbl.Rows.Remove(tr);
            }

            //Get sum of colspan
            int colspan = 0;
            if (tbl.Rows.Count > 0)
            {
                foreach (TableCell tc in tbl.Rows[0].Cells)
                {
                    colspan += (tc.ColumnSpan == 0) ? 1 : tc.ColumnSpan;
                }
            }

            //Get sum of rowspan
            int rowspan = 0;
            if (tbl.Rows.Count > 0)
            {
                foreach (TableRow tr in tbl.Rows)
                {
                    if (tr.Cells.Count > 0)
                    {
                        rowspan += (tr.Cells[0].ColumnSpan == 0) ? 1 : tr.Cells[0].ColumnSpan;
                    }
                }
            }


            //add quantity of row splitter to rowsapn.
            rowspan += (rows.Count == 0) ? 0 : rows.Count - 1;  //RowSplitter is a row.

            //Add quantity of cell splitter and cell separator to colspan
            colspan += (rows.Count == 0 || ((TableRow)rows[0]).Cells.Count == 0) ? 0 : ((TableRow)rows[0]).Cells.Count - 1;


            //Add RowSplitter below of each row except of last. 
            for (int i = 0; i < rows.Count - 1; i++)
            {
                TableRow tr = rows[i] as TableRow;
                TableRow rowSplitter = new TableRow();
                rowSplitter.SkinID = "RSPSplitterRow";

                Image img = new Image();
                img.SkinID = "RSPHSplitterImage";

                rowSplitter.Cells.Add(new TableCell());
                rowSplitter.Cells[0].Controls.Add(img);
                rowSplitter.Cells[0].ColumnSpan = colspan;
                tbl.Rows.AddAt(tbl.Rows.GetRowIndex(tr) + 1, rowSplitter);

            }


            //Add CellSplitter after each label cell. 
            if (rows.Count > 0)
            {
                //Make array of cell of first row of current table
                ArrayList cells = new ArrayList();
                foreach (TableCell tc in tbl.Rows[0].Cells)
                {
                    cells.Add(tc);
                }

                for (int i = 0; i < cells.Count - 1; i++)
                {
                    TableCell tc = cells[i] as TableCell;
                    
                    //splitter
                    TableCell cellSplitter = new TableCell();
                    cellSplitter.SkinID = "RSPCellSplitterCell";
                    

                    //seperator
                    TableCell cellSeperator = new TableCell();
                    cellSeperator.SkinID = "RSPCellSeperatorCell";

                    //image    
                    Image img = new Image();
                    img.SkinID = "RSPVSplitterImage";
                    cellSplitter.Controls.Add(img);

                    //after each pair of columns, add separator.
                    //means make splitter to seperator.
                    if (i % 2 != 0)
                    {
                        cellSplitter = cellSeperator;
                    }
                    

                    cellSplitter.RowSpan = rowspan;
                    tbl.Rows[0].Cells.AddAt(tbl.Rows[0].Cells.GetCellIndex(tc) + 1, cellSplitter);
                }
            }

            //Add invisible Rows Again
            foreach (TableRow tr in invisibleRows)
            {
                tbl.Rows.Add(tr);
            }

        }
    }

    public class RSPButtonSubDecorator : IButtonSubDecorator
    {
        public void Decorate(object obj, string caption,string ImageURL)
        {
            Table tbl = obj as Table;
            if (tbl == null)
            {
                throw new Exception("Decorated object should be a Table control");
            }
            tbl.CellPadding = tbl.CellSpacing = 0;
            tbl.BorderWidth = Unit.Pixel(0);

            //clear table
            tbl.Rows.Clear();
            

            //create row with three cells
            TableRow row = new TableRow();
            tbl.Rows.Add(row);

            TableCell cellLeftCurve = new TableCell();
            TableCell cellCaption = new TableCell();
            TableCell cellRightCurve = new TableCell();

            //left curve
            cellLeftCurve.SkinID = "RSPButtonLeftCurve";
            Image imgLeftCurve = new Image();
            imgLeftCurve.SkinID = "RSPButtonLeftImage";
            cellLeftCurve.Controls.Add(imgLeftCurve);
            row.Cells.Add(cellLeftCurve);

            //caption
            cellCaption.SkinID = "RSPButtonCaptionCell";
            Label lblCaption = new Label();
            lblCaption.Text = caption;
            lblCaption.SkinID = "RSPButtonCaption";
            cellCaption.Controls.Add(lblCaption);
            row.Cells.Add(cellCaption);



            //Right curve
            cellRightCurve.SkinID = "RSPButtonRightCurve";
            Image imgRightCurve = new Image();
            imgRightCurve.SkinID = "RSPButtonRightImage";
            cellRightCurve.Controls.Add(imgRightCurve);
            row.Cells.Add(cellRightCurve);

        }
    }


    #endregion
}